package com.flow.framework.web.helper;

import com.flow.framework.base.service.access.log.IAccessLogService;
import com.flow.framework.common.json.JsonObject;
import com.flow.framework.core.holder.OptLogI18nContextHolder;
import com.flow.framework.facade.access.log.opt.annotation.OptLog;
import com.flow.framework.facade.access.log.pojo.dto.OptLogModuleDto;
import com.flow.framework.facade.access.log.pojo.dto.TraceLogModuleDto;
import com.flow.framework.web.context.RequestResponseContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 入访日志辅助类
 *
 * @author luoguopiao
 * @version 0.0.1
 * @date 2022/12/25
 */
@Slf4j
@RequiredArgsConstructor
public class AccessLogHelper {

    private final IAccessLogService accessLogService;

    /**
     * 异步记录入访日志
     *
     * @param context context
     */
    public void asyncRecordAccessLog(RequestResponseContext context) {
        try {
            if (null == context) {
                log.error("request response context is null.");
                return;
            }
            TraceLogModuleDto traceLog = null;
            if (context.isRequireRecordTraceLog()) {
                traceLog = getTraceLog(context);
                accessLogService.asyncRecordTraceLog(traceLog);
            }

            if (null != context.getOptLog()) {
                if (null == traceLog) {
                    traceLog = getTraceLog(context);
                }
                accessLogService.asyncRecordOptLog(getOptLog(context, traceLog));
            }
        } catch (Exception e) {
            log.error("async record log error.", e);
        }
    }

    private TraceLogModuleDto getTraceLog(RequestResponseContext context) {
        long now = System.currentTimeMillis();
        long duration = now - context.getStartTime();
        TraceLogModuleDto traceLogModuleDto = new TraceLogModuleDto();
        traceLogModuleDto.setRequestTime(context.getStartTime());
        traceLogModuleDto.setResponseTime(now);
        traceLogModuleDto.setDuration((int) duration);
        traceLogModuleDto.setRequestIp(String.join(",", context.getRemoteHostAddr()));
        traceLogModuleDto.setRequestUri(context.getUri());
        traceLogModuleDto.setRequestMethod(context.getMethod());
        traceLogModuleDto.setRequestParam(JsonObject.toString(context.getOriginalRequest().getParameterMap()));
        traceLogModuleDto.setRequestContentType(context.getRequestContentType());
        traceLogModuleDto.setRequestBody(context.getRequestBody());
        traceLogModuleDto.setResponseBodyType(context.getResponseBodyType());
        traceLogModuleDto.setResponseBody(context.getResponseBody());
        traceLogModuleDto.setHttpStatus(context.getOriginalResponse().getStatus());
        return traceLogModuleDto;
    }

    private OptLogModuleDto getOptLog(RequestResponseContext context, TraceLogModuleDto traceLogModuleDto) {
        OptLogModuleDto optLogModuleDto = new OptLogModuleDto();
        optLogModuleDto.setTraceLogModuleDto(traceLogModuleDto);

        OptLog optLog = context.getOptLog();
        optLogModuleDto.setMenuCode(optLog.menuCode());
        optLogModuleDto.setVersion(optLog.version());
        optLogModuleDto.setRemark(optLog.remark());
        optLogModuleDto.setI18nParams(OptLogI18nContextHolder.getOptLogI18nParamString());
        optLogModuleDto.setIsSuccess(OptLogI18nContextHolder.isSuccess());
        OptLogI18nContextHolder.clear();
        return optLogModuleDto;
    }
}